package android.got.tasks;

import java.io.IOException;

import com.google.api.client.googleapis.auth.oauth2.draft10.GoogleAccessProtectedResource;
import com.google.api.client.googleapis.extensions.android2.auth.GoogleAccountManager;
import com.google.api.client.http.HttpResponse;
import com.google.api.client.http.HttpResponseException;

import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AccountManagerCallback;
import android.accounts.AccountManagerFuture;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;

public final class GoogleAccountActivity extends Activity {
    // our account manager for OAuth authentication
    GoogleAccountManager _accountManager;
    // initializer used to build authenticated request
    GoogleAccessProtectedResource _accessProtectedResource = new GoogleAccessProtectedResource(null);
    // identifier for our shared settings
    private static final String PREF              = "GoTasks2710";
    private static final String AUTH_TOKEN_TYPE   = "Manage your tasks";
    private static final int DIALOG_ACCOUNTS      = 22;
    private static final int REQUEST_AUTHENTICATE = 11;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        _accountManager = new GoogleAccountManager(this.getApplicationContext());

        Intent i = getIntent();
        Bundle b = i.getExtras();

        if (b != null) {
            Integer errCode = (Integer) b.getInt("ErrorCode", -1);
            if (errCode == 401) {
                gotAccount(true);
            }
        }

        gotAccount(false);
    }

    private void gotAccount(boolean tokenExpired) {
        SharedPreferences settings = getSharedPreferences(PREF, 0);
        String accountName = settings.getString("accountName", null);

        Account account = _accountManager.getAccountByName(accountName);
        if (account != null) {
            if (tokenExpired) {
                String accessToken = settings.getString("accessToken", null);
                if (accessToken != null) {
                    _accountManager.invalidateAuthToken(accessToken);
                } else {
                    _accountManager.invalidateAuthToken(_accessProtectedResource.getAccessToken());
                }
                _accessProtectedResource.setAccessToken(null);
            }
            gotAccount(account);
            return;
        }
        showDialog(DIALOG_ACCOUNTS);
    }

    private void gotAccount(final Account account) {
        Utils.writeToPref(this.getApplicationContext(), "accountName", account.name);
        RequestAuthToken(account);
      }

    private void RequestAuthToken(final Account account) {
        GetAuthTokenCallback authTokenCallback = new GetAuthTokenCallback();
        _accountManager.manager.getAuthToken(account, AUTH_TOKEN_TYPE, true, authTokenCallback, null);
    }

    protected Dialog showAccountDialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle(R.string.select_account);

        final Account[] accounts = _accountManager.getAccounts();
        final int size = accounts.length;
        String[] names = new String[size];

        for (int i = 0; i < size; i++) {
            names[i] = accounts[i].name;
        }
        
        builder.setItems(names, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                gotAccount(accounts[which]);
          }
        });

        return builder.create();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
        case REQUEST_AUTHENTICATE:
            if (resultCode == RESULT_OK) {
                gotAccount(false);
            } else {
                showDialog(DIALOG_ACCOUNTS);
            }
            break;
      }
    }

    @Override
    protected Dialog onCreateDialog(int id) {
      switch (id) {
        case DIALOG_ACCOUNTS: {
            return showAccountDialog();
        }
      }
      return null;
    }

    private void handleException(Exception e) {
        if (e instanceof HttpResponseException) {
            HttpResponse response = ((HttpResponseException) e).getResponse();
            int statusCode = response.getStatusCode();
            try {
                response.ignore();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            if (statusCode == 401) {
               gotAccount(true);
               return;
            } else if (statusCode == 412) {
                // handle conflict
                return;
            }
        }
    }

    public class GetAuthTokenCallback implements AccountManagerCallback<Bundle> {

        public void run(AccountManagerFuture<Bundle> future) {
           try {
                Bundle bundle = future.getResult();

                if (bundle.containsKey(AccountManager.KEY_INTENT)) {
                    Intent intent = bundle.getParcelable(AccountManager.KEY_INTENT);
                    intent.setFlags(intent.getFlags() & ~Intent.FLAG_ACTIVITY_NEW_TASK);
                    startActivityForResult(intent, REQUEST_AUTHENTICATE);
                } else if (bundle.containsKey(AccountManager.KEY_AUTHTOKEN)) {
                    String accessToken = bundle.getString(AccountManager.KEY_AUTHTOKEN);
                    //_accessProtectedResource.setAccessToken(accessToken);
                    SharedPreferences settings = getSharedPreferences(PREF, 0);
                    SharedPreferences.Editor editor = settings.edit();
                    editor.putString("accessToken", accessToken);
                    editor.commit();
                    setResult(Activity.RESULT_OK);
                    finish();
                }
            } catch (Exception e) {
                handleException(e);
            }
        }

    }

}